﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace SuperSearch
{
    public static class GSuggestions
    {
        public delegate void Completed(List<Suggestion> suggestions);
        public static event Completed OnComplete;
        private static string lastQuery;
        private static Dictionary<string, List<Suggestion>> cache = new Dictionary<string, List<Suggestion>>();
        public struct Suggestion : IComparable<Suggestion>, IEquatable<Suggestion>
        {
            public string Text { get; set; }
            public UInt64 Count { get; set; }

            #region IComparable<Suggestion> Members
            public int CompareTo(Suggestion other)
            {
                return (int)(other.Count - this.Count);
            }
            #endregion

            #region IEquatable<Suggestion> Members

            public bool Equals(Suggestion other)
            {
                return this.Count == other.Count && this.Text == other.Text;
            }

            #endregion
        }

        private static readonly System.Net.WebClient WebClient = new System.Net.WebClient();

        static GSuggestions()
        {
            // instanciate the webproxy class, passing the ip and port number of your proxy server
            if (!SuperSearch.Properties.Settings.Default.NoProxy)
            {
                GlobalProxySelection.Select = new WebProxy(SuperSearch.Properties.Settings.Default.ProxyAdress, int.Parse(SuperSearch.Properties.Settings.Default.ProxyPort.ToString()))
                {
                    Credentials = new NetworkCredential(SuperSearch.Properties.Settings.Default.ProxyUserName,
                        SuperSearch.Properties.Settings.Default.ProxyPassword,
                        SuperSearch.Properties.Settings.Default.ProxyDomain)
                };
            }
            WebClient.Encoding = Encoding.UTF8;
            WebClient.DownloadStringCompleted += WcDownloadStringCompleted;
        }

        public static void QueryAsync(string query)
        {
            query = query.Trim();
            if (!cache.ContainsKey(query))
            {
                lastQuery = query;
                var uri = new Uri("http://google.com/complete/search?hl=en&output=toolbar&q=" + query);
                Debug.WriteLine("->WebClient.IsBusy " + WebClient.IsBusy);
                if (WebClient.IsBusy)
                {
                    Debug.WriteLine("->CancelAsync()");
                    WebClient.CancelAsync();
                    Debug.WriteLine("<-CancelAsync()");
                }
                Debug.WriteLine("<-WebClient.IsBusy " + WebClient.IsBusy);

                Debug.WriteLine("->WebClient.IsBusy " + WebClient.IsBusy);
                if (!WebClient.IsBusy)
                {
                    Debug.WriteLine("->DownloadStringAsync() " + query);
                    WebClient.DownloadStringAsync(uri);
                    Debug.WriteLine("<-DownloadStringAsync()" + query);
                }
                Debug.WriteLine("<-WebClient.IsBusy " + WebClient.IsBusy);
            }
        }

        public static List<Suggestion> Query(string query)
        {
            query = query.Trim();
            if (!cache.ContainsKey(query))
            {
                var uri = new Uri("http://google.com/complete/search?output=toolbar&q=" + query);
                cache.Add(query, ParseResults(WebClient.DownloadString(uri)));
            }
            return cache[query];
        }

        private static void WcDownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
        {
            try
            {
                if (!e.Cancelled)
                {
                    if (!cache.ContainsKey(e.Result))
                    {
                        cache.Add(lastQuery, ParseResults(e.Result));
                    }
                    OnComplete(cache[lastQuery]);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Parses the results.
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <returns></returns>
        private static List<Suggestion> ParseResults(string xml)
        {
            var result = new List<Suggestion>();
            try
            {
                var elemSuggestions = XDocument.Parse(xml).Root.Elements("CompleteSuggestion");
                foreach (var item in elemSuggestions)
                {
                    result.Add(new Suggestion
                                   {
                                       Text = item.Element("suggestion").Attribute("data").Value,
                                       Count = UInt64.Parse(item.Element("num_queries").Attribute("int").Value)
                                   });
                }
                result.Sort();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }
    }
}
